{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "e4d14628-fbaf-4d07-b645-1a1292b8b795",
   "metadata": {},
   "outputs": [],
   "source": [
    "def fn(self, name='world'):\n",
    "    print('Hello, %s.' % name)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "ddd8d956-430b-4229-bb84-a83c355facb5",
   "metadata": {},
   "outputs": [],
   "source": [
    "Hello = type('Hello', (object,), dict(hello=fn))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "38da2568-59b7-4066-aad7-291353469c62",
   "metadata": {},
   "outputs": [],
   "source": [
    "h = Hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c828c3d6-48d4-4631-bfae-8358adc394ef",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, world.\n"
     ]
    }
   ],
   "source": [
    "h.hello()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "907f3e6f-828c-48dd-b08a-5e3653867a4c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.Hello"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(h)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "9dfaa7e9-4283-4b7c-90e8-e1dd70f8570a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, world.\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "NoneType"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "type(h.hello())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "1a925ad7-5b81-4293-902d-8618e834ddea",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ListMetaclass(type):\n",
    "    def __new__(cls, name, bases, attrs):\n",
    "        attrs['add'] = lambda self, value: self.append(value)\n",
    "        return type.__new__(cls, name, bases, attrs)\n",
    "\n",
    "class MyList(list, metaclass=ListMetaclass):\n",
    "    pass\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "af1f8d82",
   "metadata": {},
   "outputs": [],
   "source": [
    "L = MyList()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "32390d44",
   "metadata": {},
   "outputs": [],
   "source": [
    "L.add(1)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "7aee7a69",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[1]"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "L"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "d72d8fb4",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Field(object):\n",
    "\n",
    "    def __init__(self, name, column_type):\n",
    "        self.name = name\n",
    "        self.column_type = column_type\n",
    "\n",
    "    def __str__(self):\n",
    "        return \"<%s:%s>\" % (self.__class__.__name__, self.name)\n",
    "\n",
    "\n",
    "class StringField(Field):\n",
    "\n",
    "    def __init__(self, name):\n",
    "        super(StringField, self).__init__(name, \"varchar(100)\")\n",
    "\n",
    "\n",
    "class IntegerField(Field):\n",
    "\n",
    "    def __init__(self, name):\n",
    "        super(IntegerField, self).__init__(name, \"bigint\")\n",
    "\n",
    "class ModelMetaclass(type):\n",
    "    def __new__(cls, name, bases, attrs):\n",
    "        if name == 'Model': \n",
    "            return type.__new__(cls, name, bases, attrs)\n",
    "        print('Found model: %s' % name)\n",
    "        \n",
    "        mappings = dict()\n",
    "        for k, v in attrs.items():\n",
    "            if isinstance(v, Field):\n",
    "                print('Found mapping: %s ==> %s' % (k, v))\n",
    "                mappings[k] = v\n",
    "        \n",
    "        for k in mappings.keys():\n",
    "            attrs.pop(k)\n",
    "        attrs['__mappings__'] = mappings\n",
    "        attrs['__table__'] = name\n",
    "        \n",
    "        return type.__new__(cls, name, bases, attrs)\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "20727fff",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Model(dict, metaclass=ModelMetaclass):\n",
    "\n",
    "    def __init__(self, **kw):\n",
    "        super(Model, self).__init__(**kw)\n",
    "\n",
    "    def __getattr__(self, key):\n",
    "        try:\n",
    "            return self[key]\n",
    "        except KeyError:\n",
    "            raise AttributeError(r\"'Model' object has no attribute '%s'\" % key)\n",
    "\n",
    "    def __setattr__(self, key, value):\n",
    "        self[key] = value\n",
    "\n",
    "    def save(self):\n",
    "        fields = []\n",
    "        params = []\n",
    "        args = []\n",
    "        for k, v in self.__mappings__.items():\n",
    "            fields.append(v.name)\n",
    "            params.append(\"?\")\n",
    "            args.append(getattr(self, k, None))\n",
    "        sql = \"insert into %s (%s) values (%s)\" % (self.__table__, \",\".join(fields), \",\".join(params))\n",
    "        print(\"SQL: %s\" % sql)\n",
    "        print(\"ARGS: %s\" % str(args))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "a04ec906",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Found model: User\n",
      "Found mapping: id ==> <IntegerField:id>\n",
      "Found mapping: name ==> <StringField:username>\n",
      "Found mapping: email ==> <StringField:email>\n",
      "Found mapping: password ==> <StringField:password>\n"
     ]
    }
   ],
   "source": [
    "\n",
    "\n",
    "class User(Model):\n",
    "    id = IntegerField(\"id\")\n",
    "    name = StringField(\"username\")\n",
    "    email = StringField(\"email\")\n",
    "    password = StringField(\"password\")\n",
    "\n",
    "u = User(id=12345, name=\"Michael\", email=\"610848706@qq.com\", password=\"testadmin\")\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "d9eec118",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "SQL: insert into User (id,username,email,password) values (?,?,?,?)\n",
      "ARGS: [12345, 'Michael', '610848706@qq.com', 'testadmin']\n"
     ]
    }
   ],
   "source": [
    "u.save()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "39525ce8",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
